﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace WizzardTheGame
{
    class Player: Character
    {
        private static Vector3 WEAPON_OFFSET = new Vector3(-10f, 0f, 0f);
        private static Vector3 ARMOR_OFFSET = new Vector3(0f, 8f, -15f);
        private Vector3 cur_weapon_offset = WEAPON_OFFSET;
        private const float MAX_RUNSPEED = 3;
        private Bar hpbar;
        private Weapon equippedWeapon;
        private Armor equippedArmor;
        private int level;
        private PlayerState currentPlayerState;
        private bool attacking;
        private ObjectText playerCaption;

        public enum PlayerState
        {
            walking,
            jumping,
            stopped,
            stopping
        }

        #region Properties

        public ObjectText PlayerCaption
        {
            get { return playerCaption; }
            set { playerCaption = value; }
        }

        public Vector3 Cur_weapon_offset
        {
            get { return cur_weapon_offset; }
            set { cur_weapon_offset = value; }
        }

        public Bar Hpbar
        {
            get { return hpbar; }
            set { hpbar = value; }
        }

        public override Vector3 Position
        {
            get { return base.Position; }
            set
            {
                base.Position = value;
                if (EquippedWeapon != null) EquippedWeapon.Position = value + Cur_weapon_offset;
                if (EquippedArmor != null) EquippedArmor.Position = value + ARMOR_OFFSET;
            }
        }

        public PlayerState CurrentPlayerState
        {
            get { return currentPlayerState; }
            set { currentPlayerState = value; }
        }

        public bool Attacking
        {
            get { return attacking; }
            set { attacking = value; }
        }

        public Weapon EquippedWeapon
        {
            get { return equippedWeapon; }
            set { equippedWeapon = value; }
        }

        public Armor EquippedArmor
        {
            get { return equippedArmor; }
            set { equippedArmor = value; }
        }

        public int Level
        {
            get { return level; }
            set
            {
                level = value;
                Hpbar.Level.Text = Level.ToString();
            }
        }

        public override int Experience
        {
            get { return base.Experience; }
            set { 
                base.Experience = value;
                CheckLvlUp();
            }
        }

        public override int CurrentHP
        {
            get
            {
                return base.CurrentHP;
            }
            set
            {
                base.CurrentHP = value;
                Hpbar.CalcHP(MaxHP, CurrentHP);
            }
        }

        #endregion

        public Player(string path)
            :base(path)
        {
            CharModel.Rotation = new Vector3(-MathHelper.PiOver2, -MathHelper.PiOver2, 0);
            CharModel.Initial_y_rotation = -MathHelper.PiOver2;
            CharModel.Scale = 1f;
            CurrentPlayerState = PlayerState.stopped;
            Hpbar = new Bar();
            Level = 1;
            Speed = 2;
            CheckLvlUp();
            MaxHP = 1000;
            CurrentHP = MaxHP;
            Experience = 0;
            PlayerCaption = new ObjectText();
            PlayerCaption.Font = GameWorld.getInstance().Content.Load<SpriteFont>("Fonts\\Bookman");
            PlayerCaption.Position = new Vector2(GameWorld.getInstance().Graphics.Viewport.Width/2, GameWorld.getInstance().Graphics.Viewport.Height/2);
            PlayerCaption.Color = Color.DarkRed;
            PlayerCaption.AlphaValue = 255;
            PlayerCaption.IsVisible = true;
            PlayerCaption.Text = "";
        }

        private bool CheckLvlUp()
        {
            bool ok = false;
            int toNext = 100*Level*Level;
            while (Experience >= toNext)
            {
                LvlUp();
                toNext = 100 * Level * Level;
                ok = true;
            }
            hpbar.CalcEXP(toNext, Experience);
            return ok;  
        }

        private void LvlUp()
        {
            Level += 1;
            MaxHP =(int)((float)MaxHP*0.5f);
            CurrentHP = MaxHP;
            AttackPower += 10;
            Defense += 5;
            Speed += 0.05f;

        }

        private void MoveRight()
        {
            Vector3 vec;
            if (CharModel.Rotation.Y > 0)
            {
                vec = CharModel.Rotation;
                vec.Y *= -1;
                CharModel.Rotation = vec;
                //Position = Position + new Vector3(-10f, 0f, 0f);
                vec = Cur_weapon_offset;
                vec.X *= -1;
                Cur_weapon_offset = vec;
            }
            else MoveVector = Speed * RightVec;
            //CurrentPlayerState = PlayerState.walking;
        }

        private void MoveLeft()
        {
            Vector3 vec;
            if (CharModel.Rotation.Y < 0)
            {
                vec = CharModel.Rotation;
                vec.Y *= -1;
                CharModel.Rotation = vec;
                //Position = Position + new Vector3(10f, 0f, 0f);

                vec = Cur_weapon_offset;
                vec.X *= -1;
                Cur_weapon_offset = vec;
            }
            else MoveVector = Speed * LeftVec;
            //CurrentPlayerState = PlayerState.walking;
        }

        private void Stop()
        {
            MoveVector = Vector3.Zero;
        }

        private void Jump()
        {
            if (Velocity.Y == 0)
            {
                CurrentPlayerState = PlayerState.jumping;
                Vector3 vec = Velocity;
                vec.Y = 5f;
                Velocity = vec;
            }
        }

        protected override void Attack()
        {
            if (EquippedWeapon != null) EquippedWeapon.Attack();
        }

        private void CycleWeapon()
        {
            Int32 weaponindex = Inventory.Weapons.IndexOf(EquippedWeapon);
            if (weaponindex == (Inventory.Weapons.Count-1))
            {
                EquippedWeapon = Inventory.Weapons[0];
            }
            else
            {
                EquippedWeapon = Inventory.Weapons[++weaponindex];
            }
        }

        private void CycleArmor()
        {
        }

        public void PickUp(Item item)
        {
            GameWorld.getInstance().Drawables.Remove(item);
            GameWorld.getInstance().Items.Remove(item);
            Inventory.AddItem(item);
        }

        public override void Update()
        {
            if (!IsAlive) return;
            if (CurrentHP < 1)
            {
                IsAlive = false;
                PlayerCaption.Text = "Dead";
            }
            GameWorld gw = GameWorld.getInstance();
            bool xbox = true;

#if !XBOX
            xbox = false;
            if (gw.KeyboardState.IsKeyDown(Keys.F1) && !gw.PrevKeyboardState.IsKeyDown(Keys.F1) && !gw.WeaponMenu.IsActive)
            {
                gw.hideGameLevel();
                gw.showWeaponMenu();
            }

            if (gw.KeyboardState.IsKeyDown(Keys.Right))
            {
                MoveRight();
            }
            if (gw.KeyboardState.IsKeyDown(Keys.Left))
            {
                MoveLeft();
            }
            if (!(gw.KeyboardState.IsKeyDown(Keys.Left)) && !(gw.KeyboardState.IsKeyDown(Keys.Right)) && CurrentPlayerState != PlayerState.jumping)
            {
                Stop();
            }
            if (gw.KeyboardState.IsKeyDown(Keys.Space) && CurrentPlayerState != PlayerState.jumping)
            {
                Jump();
            }
            if (gw.KeyboardState.IsKeyDown(Keys.LeftAlt))
            {
                Attack();
            }
            if (gw.KeyboardState.IsKeyDown(Keys.W) && gw.PrevKeyboardState.IsKeyUp(Keys.W))
            {
                CycleWeapon();
            }
            //gw.PrevKeyboardState = gw.KeyboardState;
#endif
            if (xbox)
            {
                if(gw.GamePadState.IsButtonDown(Buttons.Start) && !gw.PrevGamePadState.IsButtonDown(Buttons.Start) && !gw.WeaponMenu.IsActive)
                {
                    gw.hideGameLevel();
                    gw.showWeaponMenu();
                }
                if (gw.GamePadState.IsButtonDown(Buttons.DPadRight))
                {
                    MoveRight();
                }
                if (gw.GamePadState.IsButtonDown(Buttons.DPadLeft))
                {
                    MoveLeft();
                }
                if (gw.GamePadState.IsButtonDown(Buttons.B) && CurrentPlayerState != PlayerState.jumping)
                {
                    Jump();
                }
                if (gw.GamePadState.IsButtonDown(Buttons.A))
                {
                    Attack();
                }
                if (gw.GamePadState.IsButtonDown(Buttons.X) && gw.PrevGamePadState.IsButtonUp(Buttons.X))
                {
                    CycleWeapon();
                }
                if (gw.GamePadState.IsButtonUp(Buttons.DPadRight) && gw.GamePadState.IsButtonUp(Buttons.DPadLeft) && CurrentPlayerState != PlayerState.jumping)
                {
                    Stop();
                }
            }

            if (CurrentPlayerState == PlayerState.jumping)
            {
                Vector3 vec = Velocity;
                if (vec.Y == 0f)
                {
                    CurrentPlayerState = PlayerState.walking;
                }
            }

            base.Update();


            //Weapon model collision with enemies on GameWorld, enemy get damage if collision, but only one time damage per attack
            int i = 0;
            bool collision = false;
            if (EquippedWeapon != null)
            {
                EquippedWeapon.Update();
                if (EquippedWeapon.Attacking)
                {
                    List<Enemy> enemies = GameWorld.getInstance().Enemies;
                    while (!collision && i < enemies.Count && !EquippedWeapon.Hashitenemy)
                    {
                        collision = enemies[i].CharModel.TestCollision(EquippedWeapon.ItemModel);
                        if (collision)
                        {
                            enemies[i].CurrentHP -= (AttackPower + EquippedWeapon.AttackPowerBonus);
                            if (enemies[i].CurrentHP < 1) Experience += enemies[i].Experience;
                            Console.WriteLine("collision");
                            EquippedWeapon.Hashitenemy = true;
                        }
                        i++;
                    }
                }
            }

            //Player model collision with item on GameWorld, player picks up item if collision
            i = 0;
            collision = false;
            List<Item> Items = GameWorld.getInstance().Items;
            while (!collision && i < Items.Count)
            {
                collision = Items[i].ItemModel.TestCollision(CharModel);
                if (collision)
                {
                    PickUp(Items[i]);
                }
                i++;
            }

            //Player model collision with enemies, player get dmg if collision
            i = 0;
            collision = false;
            List<Enemy> Enemies = GameWorld.getInstance().Enemies;
            while (!collision && i < Enemies.Count)
            {
                collision = Enemies[i].CharModel.TestCollision(CharModel);
                if (collision)
                {
                    CurrentHP -= Enemies[i].AttackPower;
                }
                i++;
            }
        }

        public override void Draw()
        {
            base.Draw();
            if (IsAlive)
            {
                if (EquippedWeapon != null) EquippedWeapon.Draw();
                if (EquippedArmor != null) EquippedArmor.Draw();
            }
        }
    }
}
